package io.dcloud.uniplugin;


import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 车架号工具类
 */
public class VinUtils {

    private static final Map<Character, Integer> CHAR_VALUE = new HashMap<>();

    /**
     * 车架号加权系数
     */
    private static final int[] frame_number_position_weight = {8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2};

    static {
        //字符权重表
        CHAR_VALUE.put('A', 1);
        CHAR_VALUE.put('B', 2);
        CHAR_VALUE.put('C', 3);
        CHAR_VALUE.put('D', 4);
        CHAR_VALUE.put('E', 5);
        CHAR_VALUE.put('F', 6);
        CHAR_VALUE.put('G', 7);
        CHAR_VALUE.put('H', 8);
        CHAR_VALUE.put('J', 1);
        CHAR_VALUE.put('K', 2);
        CHAR_VALUE.put('L', 3);
        CHAR_VALUE.put('M', 4);
        CHAR_VALUE.put('N', 5);
        CHAR_VALUE.put('P', 7);
        CHAR_VALUE.put('R', 9);
        CHAR_VALUE.put('S', 2);
        CHAR_VALUE.put('T', 3);
        CHAR_VALUE.put('U', 4);
        CHAR_VALUE.put('V', 5);
        CHAR_VALUE.put('W', 6);
        CHAR_VALUE.put('X', 7);
        CHAR_VALUE.put('Y', 8);
        CHAR_VALUE.put('Z', 9);

        CHAR_VALUE.put('0', 0);
        CHAR_VALUE.put('1', 1);
        CHAR_VALUE.put('2', 2);
        CHAR_VALUE.put('3', 3);
        CHAR_VALUE.put('4', 4);
        CHAR_VALUE.put('5', 5);
        CHAR_VALUE.put('6', 6);
        CHAR_VALUE.put('7', 7);
        CHAR_VALUE.put('8', 8);
        CHAR_VALUE.put('9', 9);
    }

    /**
     * 校验车架号是否符合车架号规则
     *
     * @param vin 车架号
     */
    public static Boolean validFrameNumber(String vin) {
        if (vin != null && !vin.trim().isEmpty()) {
            String regEx = "[A-HJ-NPR-Z0-9]{17}";
            Pattern pattern = Pattern.compile(regEx);
            Matcher matcher = pattern.matcher(vin);
            if (matcher.matches()) {
                return Objects.equals(vin, generateVinNo(vin.substring(0, 3), vin.substring(3, 8), vin.substring(9)));
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 车架号自动生成
     *
     * @param vim 世界制造厂识别代码 3位字符
     * @param vds 车辆特征 5位字符
     * @param vis 车辆指示部分 8位字符
     * @return 带校验码的17位车架号 vim + vds + validStr + vis
     */
    public static String generateVinNo(String vim, String vds, String vis) {
        int vimNum = 0, vdsNum = 0, visNum = 0;
        int position = 0;
        for (int i = 0; i < vim.length(); i++) {
            Integer value = CHAR_VALUE.get(vim.charAt(i));
            int weight = frame_number_position_weight[position + i];
            vimNum += value * weight;
        }
        position += vim.length();

        for (int i = 0; i < vds.length(); i++) {
            Integer value = CHAR_VALUE.get(vds.charAt(i));
            int weight = frame_number_position_weight[position + i];
            vdsNum += value * weight;
        }
        position += vds.length();
        position += 1;

        for (int i = 0; i < vis.length(); i++) {
            Integer value = CHAR_VALUE.get(vis.charAt(i));
            int weight = frame_number_position_weight[position + i];
            visNum += value * weight;
        }
        int valid = (vimNum + vdsNum + visNum) % 11;
        String validStr = valid == 10 ? "X" : String.valueOf(valid);

        return vim + vds + validStr + vis;
    }

    /**
     * 合格证编号加权系数
     */
    private static final int[] certificate_position_weight = {5, 4, 3, 2, 0, 9, 8, 7, 6, 5, 4, 3, 2, 8, 7};

    /**
     * 校验合格证编号
     */
    public static boolean validCertificateNo(String certificateNo) {
        if (certificateNo != null) {
            String regEx = "[A-HJ-NPR-Z0-9]{15}";
            Pattern pattern = Pattern.compile(regEx);
            Matcher matcher = pattern.matcher(certificateNo);
            if (matcher.matches()) {
                int count = 0;
                for (int i = 0; i < certificateNo.length(); i++) {
                    Integer value = CHAR_VALUE.get(certificateNo.charAt(i));
                    count += certificate_position_weight[i] * value;
                }
                int mod = count % 11;
                if (mod == 10) {
                    return certificateNo.charAt(4) == 'X';
                } else {
                    return certificateNo.charAt(4) == Integer.toString(mod).charAt(0);
                }
            }
        }
        return false;

    }
}
